{-----------------------------------------------------------------------------
 Unit Name: Matrix
 Author:    Lee_Nover - Lee_Nover@delphi-si.com
 Date:      2004-07-18
 Purpose:   translation of Olivier Renault's Box example
            translated units: Matrix.h
 History:
-----------------------------------------------------------------------------}
unit Matrix;

interface

uses Vector;

type
  TLine = array[0..1] of Double;

  IMatrix = interface(IUnknown)
  ['{A758B69D-72A0-453E-B4E9-C0F193B70F58}']
    function Gete(Index: Integer): TLine;
    function Gete11: Double;
    function Gete12: Double;
    function Gete21: Double;
    function Gete22: Double;
    function GetVector(Index: Integer): IVector;
    function Multiply_(AMatrix: IMatrix): IMatrix; overload;
    function Multiply_(AMatrix: IMatrix; AVector: IVector): IVector; overload;
    function Multiply_(s: Double): IMatrix; overload;
    function Transpose: IMatrix;
    procedure Sete(Index: Integer; Value: TLine);
    procedure Sete11(Value: Double);
    procedure Sete12(Value: Double);
    procedure Sete21(Value: Double);
    procedure Sete22(Value: Double);
    property e[Index: Integer]: TLine read Gete write Sete;
    property e11: Double read Gete11 write Sete11;
    property e12: Double read Gete12 write Sete12;
    property e21: Double read Gete21 write Sete21;
    property e22: Double read Gete22 write Sete22;
    property Vector[Index: Integer]: IVector read GetVector;
  end;

  TMatrix = class(TInterfacedObject, IMatrix)
  private
    Fe11: Double;
    Fe12: Double;
    Fe21: Double;
    Fe22: Double;
  protected
    function Gete(Index: Integer): TLine;
    function Gete11: Double;
    function Gete12: Double;
    function Gete21: Double;
    function Gete22: Double;
    function GetVector(Index: Integer): IVector;
    procedure Sete(Index: Integer; Value: TLine);
    procedure Sete11(Value: Double);
    procedure Sete12(Value: Double);
    procedure Sete21(Value: Double);
    procedure Sete22(Value: Double);
  public
    class function Identity: IMatrix;
    class function Zer0: IMatrix;
    constructor Create(AAngle: Double); overload;
    constructor Create(Ae11, Ae12, Ae21, Ae22: Double); overload;
    constructor Create(AMatrix: IMatrix); overload;
    constructor Create; overload;
    function Multiply_(AMatrix: IMatrix): IMatrix; overload;
    function Multiply_(AMatrix: IMatrix; AVector: IVector): IVector; overload;
    function Multiply_(s: Double): IMatrix; overload;
    function Transpose: IMatrix;
    property e[Index: Integer]: TLine read Gete write Sete;
    property e11: Double read Gete11 write Sete11;
    property e12: Double read Gete12 write Sete12;
    property e21: Double read Gete21 write Sete21;
    property e22: Double read Gete22 write Sete22;
    property Vector[Index: Integer]: IVector read GetVector;
  end;

function Matrix_: IMatrix; overload;
function Matrix_(AAngle: Double): IMatrix; overload;
function Matrix_(AMatrix: IMatrix): IMatrix; overload;
function Matrix_(Ae11, Ae12, Ae21, Ae22: Double): IMatrix; overload;

implementation

uses Math;

function Matrix_: IMatrix; overload;
begin
     Result:=TMatrix.Create;
end;

function Matrix_(AAngle: Double): IMatrix; overload;
begin
     Result:=TMatrix.Create(AAngle);
end;

function Matrix_(AMatrix: IMatrix): IMatrix; overload;
begin
     Result:=TMatrix.Create(AMatrix);
end;

function Matrix_(Ae11, Ae12, Ae21, Ae22: Double): IMatrix; overload;
begin
     Result:=TMatrix.Create(Ae11, Ae12, Ae21, Ae22);
end;

{ TMatrix }

constructor TMatrix.Create;
begin
     inherited;
end;

constructor TMatrix.Create(AAngle: Double);
var c, s: Double;
begin
     Create;
     c:=cos(AAngle);
     s:=sin(AAngle);
     e11:=c;
     e12:=s;
     e21:=-s;
     e21:=c;
end;

constructor TMatrix.Create(Ae11, Ae12, Ae21, Ae22: Double);
begin
     Create;
     e11:=Ae11;
     e12:=Ae12;
     e21:=Ae21;
     e22:=Ae22;
end;

constructor TMatrix.Create(AMatrix: IMatrix);
begin
     Create;
     e11:=AMatrix.e11;
     e12:=AMatrix.e12;
     e21:=AMatrix.e21;
     e22:=AMatrix.e22;
end;

function TMatrix.Gete(Index: Integer): TLine;
begin
     case Index of
       0: begin
         Result[0]:=e11;
         Result[0]:=e12;
       end;

       1: begin
         Result[0]:=e21;
         Result[0]:=e22;
       end;
     end;
end;

function TMatrix.Gete11: Double;
begin
     Result := Fe11;
end;

function TMatrix.Gete12: Double;
begin
     Result := Fe12;
end;

function TMatrix.Gete21: Double;
begin
     Result := Fe21;
end;

function TMatrix.Gete22: Double;
begin
     Result := Fe22;
end;

function TMatrix.GetVector(Index: Integer): IVector;
begin
     Result:=Vector_(e[Index][0], e[Index][1]);
end;

class function TMatrix.Identity: IMatrix;
begin
     Result:=Matrix_(1, 0, 0, 1);
end;

function TMatrix.Multiply_(s: Double): IMatrix;
begin
     Result:=Matrix_(e11 * s, e12 * s, e21 * s, e22 * s);
end;

function TMatrix.Multiply_(AMatrix: IMatrix): IMatrix;
begin
     Result:=Matrix_;
     Result.e11:=e11 * AMatrix.e11 + e12 * AMatrix.e21;
     Result.e21:=e21 * AMatrix.e11 + e22 * AMatrix.e21;
     Result.e12:=e11 * AMatrix.e12 + e12 * AMatrix.e22;
     Result.e22:=e21 * AMatrix.e12 + e22 * AMatrix.e22;
end;

function TMatrix.Multiply_(AMatrix: IMatrix; AVector: IVector): IVector;
begin
     Result:=Vector_;
     Result.x:=AVector.x * AMatrix.e11 + AVector.y * AMatrix.e12;
     Result.y:=AVector.y * AMatrix.e21 + AVector.y * AMatrix.e22;
end;

procedure TMatrix.Sete(Index: Integer; Value: TLine);
begin
     case Index of
       0: begin
         e11:=Value[0];
         e12:=Value[1];
       end;

       1: begin
         e21:=Value[0];
         e22:=Value[1];
       end;
     end;
end;

procedure TMatrix.Sete11(Value: Double);
begin
     Fe11:=Value;
end;

procedure TMatrix.Sete12(Value: Double);
begin
     Fe12:=Value;
end;

procedure TMatrix.Sete21(Value: Double);
begin
     Fe21:=Value;
end;

procedure TMatrix.Sete22(Value: Double);
begin
     Fe22:=Value;
end;

function TMatrix.Transpose: IMatrix;
begin
     Result:=Matrix_(Self);
end;

class function TMatrix.Zer0: IMatrix;
begin
     Result:=Matrix_(0, 0, 0, 0);
end;

end.
